#include <my_header.h>

#include "InternetOperator.h"
#include "Analysis.h"
#include "Stack.h"
#include "Usr.h"
#include "login.h"
#include "putsDispose.h"
#include "getsDispose.h"
#include "pwdDispose.h"
#include "lsDispose.h"
#include "cdDispose.h"
#include "mkdirDispose.h"
#include "rmdirDispose.h"
#include "rmfileDispose.h"
#include "ReadyQueue.h"


typedef struct shareRes_s {
    ReadyQueue rq;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int pipe1;
} shareRes_t;



void * longCommandFunc(void * args){
    shareRes_t * shareRes = (shareRes_t *)args;
    while(1){
        printf("ddsfsdf\n");
        pthread_mutex_lock(&shareRes->mutex);
        while(shareRes->rq.size == 0){
            pthread_cond_wait(&shareRes->cond,&shareRes->mutex); 
        }
        prams_t * pram = deleteQueueNode(&shareRes->rq);
        pthread_mutex_unlock(&shareRes->mutex);
        /* printf("%d\n",pram->sockfd); */
        /* printf("%s\n",pram->command); */
        /* printf("%s\n",pram->p1); */
        /* printf("%s\n",pram->p2); */
        /* printf("%s\n",pram->username); */
        if(strcmp(pram->command,"puts") == 0){
            putsDispose(pram->sockfd,pram->p1,pram->p2,pram->username);
            free(pram);
            write(shareRes->pipe1,"1",1);
        }
        if(strcmp(pram->command,"gets") == 0){
        }
    }
}


int main()
{
    char * ip = "192.168.220.128";
    char * port = "8888";
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port));
    addr.sin_addr.s_addr = inet_addr(ip);
    connect(sockfd,(struct sockaddr *)&addr,sizeof(addr));

    Usr usr;
    bzero(&usr,sizeof(usr));
    printf("into login\n");
    login(sockfd,&usr);
    printf("out login\n");
    
    int pipefd[2];
    pipe(pipefd);

    shareRes_t shareRes;
    readyQueueInit(&shareRes.rq);
    pthread_mutex_init(&shareRes.mutex,NULL);
    pthread_cond_init(&shareRes.cond,NULL);
    shareRes.pipe1 = pipefd[1];
    
    pthread_t pid;
    pthread_create(&pid,NULL,longCommandFunc,&shareRes);


    Stack * s = (Stack *)calloc(1,sizeof(Stack));   //路径栈
    stackInit(s);
    char * bottom = (char *)calloc(2,sizeof(char));
    bottom[0] = '/';     
    push(s,bottom);

    char buf[4096] = {0};

    int flag = 0;      //标记客户端或服务端主动退出
    
    
    int epollfd = epoll_create(1);
    addEpollNode(epollfd,sockfd);
    addEpollNode(epollfd,STDIN_FILENO);
    addEpollNode(epollfd,pipefd[0]);
    struct epoll_event ready_set[1024];
    while(1){
        char s_curpath[256] = {0};      
        if(s->size == 1){      
            s_curpath[0] = '/';
        }else{
            for(int i = 1 ; i < s->size ;++i){
                char xiegang[] = "/";
                char ass_p[64] = {0};
                memcpy(ass_p,s->str[i],strlen(s->str[i]));
                strcat(s_curpath,xiegang);
                strcat(s_curpath,ass_p);
            }
        }
        s_curpath[strlen(s_curpath)] = '$';
        printf("%s",s_curpath);
        fflush(stdout);
        int epoll_ret = epoll_wait(epollfd,ready_set,5,-1);     
        for(int i = 0 ; i < epoll_ret ; ++i){
            if(ready_set[i].data.fd == STDIN_FILENO){
                bzero(buf,sizeof(buf));
                int rret = read(STDIN_FILENO,buf,sizeof(buf));
                if(buf[0] == '\n'){
                    break;
                }
                if(rret == 0){
                    flag = 1;   
                    break;
                }
                int pose_ret;
                char * p ;
                char * cpath;
                char * spath;
                prams_t * pram = NULL;
                switch (analysis(buf,sockfd)) {   // 不同命令返回值不同，根据返回值判断时候向后台传参
                case 0:
                    pose_ret = cdDispose(buf,sockfd,s);  //一、更新并检查路径对不对。（防止越界）二、向后台发送路径看有没有 三、更新路径栈
                    /* printf("cd返回值%d\n",pose_ret); */
                    break;
                case 1:
                    lsDispose(sockfd,s_curpath);
                    break;
                case 2:
                    pwdDispose(s);
                    break;
                case 3:
                    p = checkPath(buf,s,0);
                    if(p == NULL){
                        break;
                    }
                    mkdirDispose(p,sockfd,s_curpath);
                    break;
                case 4:
                    p = checkPath(buf,s,0);
                    if(p==NULL){
                        break;
                    }
                    rmdirDispose(p,sockfd);
                    break;
                case 5:
                    p = checkPath(buf,s,0);
                    if(p == NULL){
                        break;
                    }
                    rmfileDispose(p,sockfd);
                    break;
                case 6:
                    pram = (prams_t*)calloc(1,sizeof(prams_t));
                    memcpy(pram->command,buf,4);
                    pram->sockfd = sockfd;
                    strtok(buf," ");
                    cpath = strtok(NULL," ");
                    spath = strtok(NULL," ");
                    if(spath != NULL){
                        p = checkPath(spath,s,1);
                    }else{
                        char ass_p[] = "./";
                        p = checkPath(ass_p,s,1);
                        if( p == NULL ){
                            break;
                        }
                    }
                    memcpy(pram->p1,cpath,strlen(cpath));
                    memcpy(pram->p2,p,strlen(p));
                    memcpy(pram->username,usr.usrname,strlen(usr.usrname));
                    pthread_mutex_lock(&shareRes.mutex);
                    addQueueNode(&shareRes.rq,pram);
                    pthread_cond_broadcast(&shareRes.cond);
                    pthread_mutex_unlock(&shareRes.mutex);
                    break;
                case 7:
                    strtok(buf," ");
                    spath = strtok(NULL," ");
                    cpath = strtok(NULL," ");
                    if(spath != NULL){
                        p = checkPath(spath,s,1);
                    }else{
                        char ass_p[] = "./";
                        p = checkPath(ass_p,s,1);
                        if( p == NULL ){
                            break;
                        }
                    }
                    printf("p:%s\n",p);
                    pose_ret = getsDispose(sockfd,p,cpath);    
                    printf("gets返回值%d\n",pose_ret);
                    break;
                default:
                    printf("未知命令\n");
                    break;
                }
            }else if(ready_set[i].data.fd == pipefd[0]){
                char c;
                read(ready_set[i].data.fd,&c,1);
                continue;
            }
            else if(ready_set[i].data.fd == sockfd){
                bzero(buf,sizeof(buf));
                int rret = recv(sockfd,buf,sizeof(buf),MSG_WAITALL);
                if(rret == 0){
                    flag = 1;
                    break;
                }
            }
        }
        if(flag == 1){
            break;
        }
    }
    return 0;
}

